package com.asset.dispoal.business.repayment.service.command;

import com.asset.dispoal.business.mediation.domain.db.FormulaData;
import com.asset.dispoal.business.mediation.domain.db.mapper.ReduceOperateMapper;
import com.asset.dispoal.business.repayment.domain.db.mapper.RepaymentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import tech.mhuang.pacebox.core.date.DateTimeUtil;
import tech.mhuang.pacebox.core.util.StringUtil;
import tech.mhuang.pacebox.springboot.protocol.Result;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description: 根据公式计算罚息接口
 * @author: yf
 * @date: 2022-09-28 09:20:35
 */
@Repository
public class GetPenaltyInterestByFormularCommand {
    @Autowired
    private ReduceOperateMapper operateMapper;
    @Autowired
    private RepaymentMapper repaymentMapper;

    /**
     * 1.根据案件id拿到计算公式参数，将公式对应的参数解解析为p1, p2 ,p3, days
     * 2.判断formula_id 是否为空，为空则执行简单公式 p1 * p2 * (当前时间 - 逾期时间)/p3/days
     * formula_id  不为空，则执行动态规则
     *
     * @return
     */
    public Result execute(String caseId, String batchParameterId) {
        HashMap<String, Object> hashMap = new HashMap<>(1);
        //获取公式对应信息
        Map<String, String> formulaMap = repaymentMapper.getFormulaInfoById(batchParameterId);
        if (null != formulaMap) {
            List<String> s = Arrays.asList(formulaMap.get("parameter1"), formulaMap.get("parameter2"), formulaMap.get("parameter3"));
            //参数值映射
            List<Map<String, String>> dataMap = operateMapper.queryParameterMapping(s);
            List<Map<String, Object>> mapList = repaymentMapper.queryFormularAndBorrower(dataMap, caseId, batchParameterId);
            //执行简单公式
            if (!formulaMap.containsKey("formula_id") || StringUtil.isEmptyNull(formulaMap.get("formula_id"))) {
                hashMap.put("penaltyInterest", penaltyInterestCalculate(mapList));
                return Result.ok(hashMap);
            } else {
                String formulaId = formulaMap.get("formula_id");
                List<FormulaData> formulaDataList = operateMapper.queryFormulaDataById(formulaId);
                if (CollectionUtils.isEmpty(formulaDataList)) {
                    hashMap.put("penaltyInterest", BigDecimal.ZERO);
                    return Result.ok(hashMap);
                }
                hashMap.put("penaltyInterest", dynamicPenaltyInterestCalculate(mapList, formulaDataList));
                return Result.ok(hashMap);
            }
        } else {
            hashMap.put("penaltyInterest", BigDecimal.ZERO);
            return Result.ok(hashMap);
        }
    }

    /**
     * 动态规则计算
     *
     * @param mapList
     * @param formulaDataList
     */
    private BigDecimal dynamicPenaltyInterestCalculate(List<Map<String, Object>> mapList, List<FormulaData> formulaDataList) {
        BigDecimal penaltyInterest = BigDecimal.ZERO;
        for (Map<String, Object> agreementData : mapList) {
            LocalDate parameter3 = LocalDate.parse(agreementData.get(agreementData.get("parameter3")).toString());
            LocalDate currentDate = LocalDate.parse(agreementData.get("sueDate").toString());
            Long days = DateTimeUtil.getLocalDateDiffDay(parameter3, currentDate);
            if (days >= 0) {
                for (FormulaData formulaData : formulaDataList) {
                    //判断结束时间是否为空  为空改为当前时间
                    if (null == formulaData.getEndTime()) {
                        formulaData.setEndTime(LocalDate.now());
                    }

                    //如果逾期开始时间在公式结束时间后则跳过
                    if (parameter3.isAfter(formulaData.getEndTime())) {
                        continue;
                    }
                    LocalDate beforeTime = formulaData.getStartTime();
                    if (parameter3.isAfter(formulaData.getStartTime())) {
                        beforeTime = parameter3;
                    }
                    LocalDate afterTime = formulaData.getEndTime();
                    if (currentDate.isBefore(formulaData.getEndTime())) {
                        afterTime = currentDate;
                    }
                    BigDecimal parameter1 = (BigDecimal) agreementData.get(agreementData.get("parameter1"));
                    Integer p4 = (Integer) agreementData.get("parameter4");

                    Long diffDay = DateTimeUtil.getLocalDateDiffDay(beforeTime, afterTime);
                    penaltyInterest = penaltyInterest.add(parameter1.multiply(formulaData.getRate()).multiply(BigDecimal.valueOf(diffDay)).divide(
                            BigDecimal.valueOf(p4), 2, RoundingMode.HALF_UP
                    ));
                }
            }
        }
        return penaltyInterest.setScale(2, RoundingMode.HALF_UP);
    }


    /**
     * 简单公式算取罚息
     * 罚息计算 p1 * p2 * (当前时间(sueDate) - 逾期时间(p3)/days(p4)
     *
     * @param mapList
     */
    private BigDecimal penaltyInterestCalculate(List<Map<String, Object>> mapList) {
        BigDecimal result = BigDecimal.ZERO;
        for (Map<String, Object> agreementMap : mapList) {
            BigDecimal p1 = (BigDecimal) agreementMap.get(agreementMap.get("parameter1"));
            BigDecimal p2 = (BigDecimal) agreementMap.get(agreementMap.get("parameter2"));
            LocalDate p3 = LocalDate.parse(agreementMap.get(agreementMap.get("parameter3")).toString());
            LocalDate currentDate = LocalDate.parse(agreementMap.get("sueDate").toString());
            Integer p4 = (Integer) agreementMap.get("parameter4");
            Long diffDay = DateTimeUtil.getLocalDateDiffDay(p3, currentDate);

            result = result.add(
                    p1.multiply(p2)
                            .multiply(BigDecimal.valueOf(diffDay))
                            .divide(BigDecimal.valueOf(p4), RoundingMode.HALF_UP)
            );
        }
        return result.setScale(2, RoundingMode.HALF_UP);
    }
}
